package com.just.springbootintegration.config;

import com.rometools.rome.feed.synd.SyndEntry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.channel.MessageChannels;
import org.springframework.integration.dsl.core.Pollers;
import org.springframework.integration.dsl.file.Files;
import org.springframework.integration.dsl.mail.Mail;
import org.springframework.integration.feed.inbound.FeedEntryMessageSource;
import org.springframework.integration.file.support.FileExistsMode;
import org.springframework.integration.scheduling.PollerMetadata;
import java.io.File;
import java.io.IOException;

import static org.springframework.core.SpringProperties.getProperty;

/**
 * 本配置的作用
 * 从网页http://spring.io/blog.atom获取资源
 * releases 内容保存在release.txt文件里
 * engineering 内容保存在engineering.txt文件里
 * releases 部分内容发送到邮箱里（原教程是发送news的内容，然而并没有）
 */
@Configuration
public class IntegrationConfig {
    /**
     * 使用@Value注解自动获取http://spring.io/blog.atom资源
     */
    @Value("http://spring.io/blog.atom")
    Resource resource;

    /**
     * 保存邮箱配置参数的类，自动配置
     */
    @Autowired
    MyMailConfig myMailConfig;

    /**
     * 使用FluentAPI和Pollers配置的默认轮询条件
     */
    @Bean(name=PollerMetadata.DEFAULT_POLLER)
    public PollerMetadata poller(){
        return Pollers.fixedDelay(500).get();
    }

    /**
     * FeedEntryMessageSource实际上是feed:inbound-channel-adapter,即构造feed的入站通道适配器作为数据输入
     */
    @Bean
    public FeedEntryMessageSource feedMessageSource() throws IOException {
        FeedEntryMessageSource source=new FeedEntryMessageSource(resource.getURL(),"news");
        return source;
    }

    /**
     * 配置IntegrationFlow定义系统继承流程
     * 通过route来选择路由，消息体（payload）的类型为SyndEntry，作为判断条件的类型为String,判断的值是通过payload获得的分类Categroy
     * 通过不同分类的值转向不同的消息通道
     */
    @Bean
    public IntegrationFlow myFlow() throws IOException {
        return IntegrationFlows.from(feedMessageSource())      //系统流程从from开始
                .<SyndEntry,String> route(payload->
                    payload.getCategories().get(0).getName(),
                        mapping->mapping.channelMapping("releases","releasesChannel")
                        .channelMapping("engineering","engineeringChannel")
                        .channelMapping("releases","newsChannel")        //网站上没有news，用这个测试吧
                ).get();
    }

    /**
     * releases流程
     * 用handle方法处理file的出站适配器
     */
    @Bean
    public IntegrationFlow releaseFlow(){
        return IntegrationFlows.from(MessageChannels.queue("releasesChannel"))
                .<SyndEntry,String> transform(payload->"《"+payload.getTitle()+"》"+payload.getLink()+getProperty("line.separator"))
                .handle(Files.outboundAdapter(new File("d:/springblog"))
                        .fileExistsMode(FileExistsMode.APPEND)
                        .charset("UTF-8")
                        .fileNameGenerator(message -> "releases.txt")
                ).get();
    }

    /**
     * engineering流程
     * 用handle方法处理file的出站适配器
     */
    @Bean
    public IntegrationFlow engineeringFlow(){
        return IntegrationFlows.from(MessageChannels.queue("engineeringChannel"))
                .<SyndEntry,String> transform(payload->"《"+payload.getTitle()+"》"+payload.getLink()+getProperty("line.separator"))
                .handle(Files.outboundAdapter(new File("d:/springblog"))
                        .fileExistsMode(FileExistsMode.APPEND)
                        .charset("UTF-8")
                        .fileNameGenerator(message -> "engineeringChannel.txt")
                ).get();
    }

    /**
     * news流程
     * 用handle方法发送邮件
     * 这里有个坑，网站上并没有news的内容，不能触发发送邮件的操作
     * 所有在配置通道的时候，对应的key我选择了releases，详见myFlow()
     * 此处加个filter，只发送这条消息，刚开始测试的时候我的邮箱收到太多次消息了，mmp
     */
    @Bean
    public IntegrationFlow newsFlow(){
        return IntegrationFlows.from(MessageChannels.queue("newsChannel",10))
                .<SyndEntry,String> transform(payload->"《"+payload.getTitle()+"》"+payload.getLink()+getProperty("line.separator"))
                .filter(payload->payload.toString().startsWith("《Spring Security 5.0.7 Released"))
                .enrichHeaders(Mail.headers()
                               .subject("来自Spring的新闻")
                               .to(myMailConfig.getTo())
                               .from(myMailConfig.getFrom())

                )
                .handle(Mail.outboundAdapter(myMailConfig.getHost())
                        .port(myMailConfig.getPort())
                        .protocol(myMailConfig.getProtocol())
                        .credentials(myMailConfig.getUsername(),myMailConfig.getPassword())
                        .javaMailProperties(p->p.put("mail.debug",true)),
                        e->e.id("stmpOut")
                ).get();
    }
}
